#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include <functional>
#include "Socket.hpp"
using namespace SocketModule;

const std::string sep = "\r\n";
// content_len jsonstring
// 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
// 50
// {"x": 10, "y" : 20, "oper" : '+'}

//client->server
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }
    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Reader reader;
        Json::Value root;
        // 从字符串中读取JSON数据
        bool parsingSuccessful = reader.parse(in, root);
        if (!parsingSuccessful)
        {
            std::cout << "Failed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }
        else
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }

    }
     ~Request() {}
    int X(){return _x;}
    int Y(){return _y;}
    char Oper(){return _oper;}

private:
    int _x;
    int _y;
    char _oper;
};

//server->client
class Response
{
    public:
     Response()
     {

     }
     Response(int result, int code) :_result(result), _code(code)
     {

     }
     std::string Serialize()
     {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        return writer.write(root);
     }
    bool Deserialize(std::string& in)
    {
        Json::Reader reader;
        Json::Value root;
        //从字符串中读取JSON数据
        bool ok = reader.parse(in, root);
        //访问JSON数据
        if(ok)
        {
             _result = root["result"].asInt();
            _code = root["code"].asInt();
        } 
        return ok;  
    }
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    void ShowResult()
    {
        std::cout << "计算结果是： " << _result << "[" << _code <<"]" <<std::endl;
    }

     ~Response(){}
    private:
        int _result; //运算结果
        int _code;// 0:sucess;1,2,3,4分别对应不同的运算异常情况
};

// 协议(基于TCP的)需要解决两个问题：
// 1、request和response必须得有序列化和反序列化
// 2、读取到完整的请求
using func_t = std::function<Response(Request &)>;
class Protocol
{
public:

    Protocol(){}
    Protocol(func_t func) : _func(func)
    {
    }

    std::string Encode(const std::string &json)
    {
        // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
        std::string len = std::to_string(json.size());
        return len + sep + json + sep; // 应用层报头封装
    }

    // packge是输出型参数
    // 该接口：1、判断报文完整性 2、如果包含至少一个完整报文，提取它并移出，方便处理下一个
    bool Decode(std::string &buffer, std::string *packge)
    {
        ssize_t pos = buffer.find(sep);
        if(pos == -1)
         return false; //让调用方继续从内核中读取数据
        std::string packge_len_str = buffer.substr(0, pos); //获取有效载荷长度字符串
        int packge_len_int = std::stoi(packge_len_str);//获取有效载荷长度

        //判断buffer中是否有完整报文：长度+"\r\n"的长度 + 内容长度 + "\r\n"的长度
        int target_len = packge_len_str.size() + packge_len_int + 2 * sep.size();
        if(buffer.size() < target_len)
          return false;
        
        //buffer一定至少有一个完整报文
        *packge = buffer.substr(pos + sep.size(), packge_len_int);
        buffer.erase(0, target_len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &socket, InetAddr &client)
    {
        // 读取
        std::string buffer_queue;
        while (true)
        {
            int n = socket->Recv(&buffer_queue);
            if (n > 0)
            {
                std::cout << "-----------request_buffer--------------" << std::endl;
                std::cout << buffer_queue << std::endl;
                std::cout << "------------------------------------" << std::endl;

                std::string json_package;
                // 1. 解析报文，提取完整的json请求，如果不完整，让服务器继续获取
                while(Decode(buffer_queue, &json_package)) 
                {
                    // 2. 请求json串，反序列化
                    LOG(LogLevel::DEBUG) << client.StringAddr() << "请求：" <<json_package;

                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if (!ok)
                        continue;

                    // 3.一定得到了一个内部属性已经被设置的req
                    // req->resp：完成计算功能，回调出去
                    Response resp = _func(req);

                    // 4.序列化
                    std::string json_str = resp.Serialize();

                    // 5.添加自定义长度
                    // 携带长度的应答报文了"len\r\n{result:XXX, code:XX}\r\n"
                    std::string send_str = Encode(json_str);

                    // 6.发送到网络
                    socket->Send(json_str);
                }
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }

    bool GetResponse(std::shared_ptr<Socket>& client, std::string& resp_buff, Response* resp)
    {
        while(true)
        {
            int n =client->Recv(&resp_buff);
            //读取成功
            if(n > 0)
            {
                std::string json_package;
                while(Decode(resp_buff, &json_package))
                {
                    resp->Deserialize(json_package);
                }
                return true;
            }
            else if(n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }

    std::string BuildRequestString(int x, int y, char oper)
    {
        //1、构建一个完整请求
        Request req(x, y, oper);
        //2、序列化
        std::string json_req = req.Serialize();
        //3、添加报头
       return Encode(json_req);  
    }

    ~Protocol()
    {
    }

private:
    func_t _func;
};